package com.xxx.video.commen.views.recyclerviews;

import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.xxx.video.R;
import com.xxx.video.commen.utils.StringUtils;


public class RefreshHeadView extends LinearLayout {
    /**
     * tip text
     */
    private TextView mTvRefreshHeadViewTip;
    /**
     * refresh finish
     */
    public static final int STATE_REFRESH_IDLE = 301;
    /**
     * it will refresh
     */
    public static final int STATE_RELEASE_TO_REFRESH = 302;
    /**
     * refreshing
     */
    public static final int STATE_REFRESH_ING = 303;
    /**
     * refresh finish
     */
    public static final int STATE_REFRESH_COMPLETE = 304;

    /**
     * refresh status
     */
    private int mRefreshState = STATE_REFRESH_IDLE;
    /**
     * height
     */
    private int mMeasuredHeight;
    /**
     * view
     */
    private View mHeadView;

    public RefreshHeadView(Context context) {
        super(context);
        /*
         * init
         */
        init(context);
    }

    public RefreshHeadView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        /*
         * init
         */
        init(context);
    }

    public RefreshHeadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        /*
         * init
         */
        init(context);
    }

    /**
     * init
     *
     * @param context context
     */
    private void init(Context context) {
        mHeadView = View.inflate(context, R.layout.refresh_head_view, null);
        //width and height
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        //set margin
        lp.setMargins(0, 0, 0, 0);
        //setLayoutParams
        this.setLayoutParams(lp);
        addView(mHeadView, new LayoutParams(LayoutParams.MATCH_PARENT, 0));
        //setGravity
        setGravity(Gravity.BOTTOM);
        /*
         * init view
         */
        initView();
        //measure
        measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        //get height
        mMeasuredHeight = getMeasuredHeight();
    }

    /**
     * init view
     */
    private void initView() {
        mTvRefreshHeadViewTip = findViewById(R.id.tv_refresh_head_view_tip);
    }

    /**
     * this is a animation to change height
     *
     * @param height height
     */
    private void smoothScrollTo(int height) {
        ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), height);
        animator.setDuration(300).start();
        animator.addUpdateListener(animation -> setVisibleHeight((int) animation.getAnimatedValue()));
        animator.start();
    }

    /**
     * set visible height
     *
     * @param height set height
     */
    public void setVisibleHeight(int height) {
        if (height < 0) {
            height = 0;
        }
        LayoutParams layoutParams = (LayoutParams) mHeadView.getLayoutParams();
        layoutParams.height = height;
        mHeadView.setLayoutParams(layoutParams);
    }

    /**
     * get visible height
     *
     * @return get visible height
     */
    public int getVisibleHeight() {
        LayoutParams layoutParams = (LayoutParams) mHeadView.getLayoutParams();
        return layoutParams.height;
    }

    /**
     * move
     *
     * @param delta delta
     */
    public void onMove(float delta) {
        if (getVisibleHeight() > 0 || delta > 0) {
            setVisibleHeight((int) delta + getVisibleHeight());

            /*
             * if not refreshing
             */
            if (mRefreshState <= STATE_RELEASE_TO_REFRESH) {
                /*
                 * if visible height more than header view height, then set state
                 */
                if (getVisibleHeight() > mMeasuredHeight) {
                    /*
                     * set refreshing state
                     */
                    setState(STATE_RELEASE_TO_REFRESH);
                } else {
                    setState(STATE_REFRESH_IDLE);
                }
            }
        }
    }

    /**
     * set state
     *
     * @param state state
     */
    public void setState(int state) {
        if (state == mRefreshState) {
            return;
        }
        switch (state) {
            case STATE_REFRESH_IDLE:
                /*
                 * no state
                 */
                mTvRefreshHeadViewTip.setText(StringUtils.getInstance().getString(R.string.tip_refresh_recycler_view_header_pull_refresh));
                break;
            case STATE_REFRESH_COMPLETE:
                /*
                 * refresh finish
                 */
                mTvRefreshHeadViewTip.setText(StringUtils.getInstance().getString(R.string.tip_refresh_recycler_view_header_refresh_finish));
                break;
            case STATE_REFRESH_ING:
                /*
                 * refreshing
                 */
                mTvRefreshHeadViewTip.setText(StringUtils.getInstance().getString(R.string.tip_refresh_recycler_view_header_refreshing));
                break;
            case STATE_RELEASE_TO_REFRESH:
                /*
                 *  release refresh
                 */
                mTvRefreshHeadViewTip.setText(StringUtils.getInstance().getString(R.string.tip_refresh_recycler_view_header_release_refresh));
                break;
            default:
                break;
        }
        /*
         * set current state
         */
        mRefreshState = state;
    }

    /**
     * get status
     *
     * @return status
     */
    public int getRefreshState() {
        return mRefreshState;
    }

    /**
     *  release action
     *
     * @return is refresh
     */
    public boolean releaseAction() {
        //is refresh
        boolean isOnRefresh = false;
        //get visible height
        int height = getVisibleHeight();
        if (height == 0) {
            //no refresh
            isOnRefresh = false;
        }
        if (getVisibleHeight() > mMeasuredHeight && mRefreshState < STATE_REFRESH_ING) {
            setState(STATE_REFRESH_ING);
            /*
             *refreshing
             */
            isOnRefresh = true;
        }
        /*
         * reset height,if refreshing,set refreshing height
         */
        int destHeight = 0;
        if (mRefreshState == STATE_REFRESH_ING) {
            destHeight = mMeasuredHeight;
        }
        /*
         * scroll and change height
         */
        smoothScrollTo(destHeight);
        return isOnRefresh;
    }

    /**
     * refresh complete
     */
    public void refreshComplete() {
        setState(STATE_REFRESH_COMPLETE);
        new Handler().postDelayed(this::resetHeight, 200);
    }

    /**
     * reset height
     */
    public void resetHeight() {
        smoothScrollTo(0);
        new Handler().postDelayed(() -> setState(STATE_REFRESH_IDLE), 500);
    }
}
